﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Coleotrack.Common.Registration;
using Coleotrack.Core.Helper;
using Coleotrack.Data;
using Coleotrack.Models.Setup;
using Coleotrack.Service.Contracts;
using NHibernate;
using StructureMap;

namespace Coleotrack.Controllers
{
    [IfNotInstalled]
    public class SetupController : Controller
    {
        private readonly IDatabaseConnector databaseConnector;

        public SetupController(IDatabaseConnector databaseConnector)
        {
            this.databaseConnector = databaseConnector;
        }

        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Database()
        {
            var model = Session["Setup.Database"] ?? new DatabaseViewModel();
            return View(model);
        }

        [HttpPost]
        public ActionResult Database(DatabaseViewModel databaseViewModel)
        {
            if (!ValidateDatabase(databaseViewModel))
            {
                return View(databaseViewModel);
            }

            Session["Setup.Database"] = databaseViewModel;

            return RedirectToAction("Authentication", "Setup");
        }

        [HttpGet]
        public ActionResult Authentication()
        {
            var model = Session["Setup.Authentication"] ?? new AuthenticationViewModel();
            return View(model);
        }

        [HttpPost]
        public ActionResult Authentication(AuthenticationViewModel authenticationViewModel)
        {
            if (!ValidateAuthentication(authenticationViewModel))
            {
                return View(authenticationViewModel);
            }

            Session["Setup.Authentication"] = authenticationViewModel;

            return RedirectToAction("Finish", "Setup");
        }

        [HttpGet]
        public ActionResult Finish()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Close()
        {
            if (!FinishSetup())
            {
                return View("Error");
            }

            return RedirectToAction("Logon", "Account");
        }

        private bool FinishSetup()
        {
            try
            {
                string connectionString = GetConnectionString();
                var authenticationViewModel = (AuthenticationViewModel)Session["Setup.Authentication"];
                Bootstrapper.BootstrapWithDatabase(connectionString, true);

                var session = ObjectFactory.GetInstance<ISession>();

                var administrator = new User
                {
                    Name = authenticationViewModel.Username,
                    Password = authenticationViewModel.Password.Md5(),
                    Email = authenticationViewModel.Email,
                    Active = true,
                    Created = DateTime.Now,
                    Profile = new UserProfile
                    {
                        FirstName = authenticationViewModel.Firstname,
                        LastName = authenticationViewModel.Lastname
                    }
                };

                session.Save(administrator);

                MvcApplication.ApplicationSettingsLoader.Settings.ConnectionString = connectionString;
                MvcApplication.ApplicationSettingsLoader.Settings.IsInstalled = true;
                MvcApplication.ApplicationSettingsLoader.Save(Server.MapPath(ApplicationConstants.PathToApplicationSettings));

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        private string GetConnectionString()
        {
            return ((DatabaseViewModel)Session["Setup.Database"]).ConnectionString;
        }

        private bool ValidateDatabase(DatabaseViewModel databaseViewModel)
        {
            if (string.IsNullOrEmpty(databaseViewModel.Host))
            {
                ModelState.AddModelError("Host", "Please provide a valid host name");
            }

            if (databaseViewModel.IntegratedAuth)
            {
                if (string.IsNullOrEmpty(databaseViewModel.Username))
                {
                    ModelState.AddModelError("Host", "Please provide a valid username");
                }

                if (string.IsNullOrEmpty(databaseViewModel.Password))
                {
                    ModelState.AddModelError("Host", "Please provide a valid password");
                }
            }

            if (string.IsNullOrEmpty(databaseViewModel.Database))
            {
                ModelState.AddModelError("Database", "Please provide a valid database name");
            }

            if (ModelState.IsValid)
            {
                // Check database
                if (!CheckDatabase(databaseViewModel))
                {
                    ModelState.AddModelError("_FORM", "Connect to the database was not successfull.");
                }
            }

            return ModelState.IsValid;
        }

        private bool CheckDatabase(DatabaseViewModel databaseViewModel)
        {
            return databaseConnector.ConnectionIsValid(
                databaseViewModel.Host, 
                databaseViewModel.IntegratedAuth, 
                databaseViewModel.Username, 
                databaseViewModel.Password, 
                databaseViewModel.Database);
        }

        private bool ValidateAuthentication(AuthenticationViewModel authenticationViewModel)
        {
            if (string.IsNullOrEmpty(authenticationViewModel.Username))
            {
                ModelState.AddModelError("Username", "Please provide a username");
            }

            if (!authenticationViewModel.Email.IsValidEmailAddress())
            {
                ModelState.AddModelError("Email", "Please provide a valid email-adress");
            }

            if (string.IsNullOrEmpty(authenticationViewModel.Firstname))
            {
                ModelState.AddModelError("Firstname", "Please provide your first name");
            }

            if (string.IsNullOrEmpty(authenticationViewModel.Lastname))
            {
                ModelState.AddModelError("Lastname", "Please provide your lastname");
            }

            if (string.IsNullOrEmpty(authenticationViewModel.Password))
            {
                ModelState.AddModelError("Password", "Please provide a password");
            }

            if (string.IsNullOrEmpty(authenticationViewModel.PasswordConfirmation))
            {
                ModelState.AddModelError("Username", "Please confirm your password");
            }

            if (
                authenticationViewModel.Password != null && 
                authenticationViewModel.PasswordConfirmation != null &&
                authenticationViewModel.Password != authenticationViewModel.PasswordConfirmation)
            {
                ModelState.AddModelError("Username", "Password and the confirmation must be equal");
            }

            return ModelState.IsValid;
        }
    }
}
